﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using System.IO;
using GoodStuff.Text;

namespace GoodStuff.UnitTests.LowLevelCSV
{
    [TestFixture]
    public class TestCSVStreamReader
    {
        [Test]
        public void TestConstructor()
        {
            StringReader stringReader = new StringReader("Hello,world\r\n");
            CSVStreamReader reader = new CSVStreamReader(stringReader, ",");
        }

        [Test]
        public void TestHasNoLines()
        {
            StringReader stringReader = new StringReader("");
            CSVStreamReader reader = new CSVStreamReader(stringReader, ",");
            Assert.IsTrue(reader.EndOfFile);
        }

        [Test]
        public void TestHasLines()
        {
            StringReader stringReader = new StringReader("Hello,world");
            CSVStreamReader reader = new CSVStreamReader(stringReader, ",");
            Assert.IsFalse(reader.EndOfFile);
        }

        [Test]
        public void TestCountColumns()
        {
            StringReader stringReader = new StringReader("Hello,world");
            CSVStreamReader reader = new CSVStreamReader(stringReader, ",");
            Assert.AreEqual(2, reader.Columns);
        
        }

        [Test]
        public void TestCountColumnsSeparator()
        {
            StringReader stringReader = new StringReader("Hello,world");
            CSVStreamReader reader = new CSVStreamReader(stringReader, ";");
            Assert.AreEqual(1, reader.Columns);

        }

        [Test]
        public void TestCountColumns2Rows()
        {
            StringReader stringReader = new StringReader("Hello,world\r\nAnother row");
            CSVStreamReader reader = new CSVStreamReader(stringReader, ";");
            Assert.AreEqual(1, reader.Columns);

            Assert.AreEqual("Hello,world", reader[0]);

        }

        [Test]
        public void VeriftEmptyRowHasNoColumns()
        {
            StringReader stringReader = new StringReader("\r\n");
            CSVStreamReader reader = new CSVStreamReader(stringReader, ";");
            Assert.IsFalse(reader.EndOfFile);
            Assert.AreEqual(0, reader.Columns);
        }     

         [Test]
         [ExpectedException(typeof(IndexOutOfRangeException))]
         public void TestInvalidColumnIndex()
         {
             StringReader stringReader = new StringReader("Aap\r\n");
             CSVStreamReader reader = new CSVStreamReader(stringReader, ";");
             Assert.IsFalse(reader.EndOfFile);
             Assert.AreEqual(1, reader.Columns);

             var x = reader[1];

         }

        [Test]
        public void TestColumnContainsSeparator()
        {
            StringReader stringReader = new StringReader("\";\";two");
            CSVStreamReader reader = new CSVStreamReader(stringReader, ";");
            Assert.IsFalse(reader.EndOfFile);
            Assert.AreEqual(2, reader.Columns, "only 2 columns expected");
            Assert.AreEqual(";", reader[0]);
            Assert.AreEqual("two", reader[1]);
        }

        [Test]
        public void TestColumnContainsEscapeSequence()
        {
            StringReader stringReader = new StringReader("\"\"\"\";two"); //-> """";two
            CSVStreamReader reader = new CSVStreamReader(stringReader, ";");
            Assert.IsFalse(reader.EndOfFile);
            Assert.AreEqual(2, reader.Columns, "only 2 columns expected");
            Assert.AreEqual("\"", reader[0]);
            Assert.AreEqual("two", reader[1]);
        }

        [Test]
        public void TestColumnContainsMultipleEscapeSequence()
        {
            StringReader stringReader = new StringReader("\"\"\"hello\"\";\"\"world\"\"\";two");
            CSVStreamReader reader = new CSVStreamReader(stringReader, ";");
            Assert.IsFalse(reader.EndOfFile);
            Assert.AreEqual(2, reader.Columns, "only 2 columns expected");
            Assert.AreEqual("\"hello\";\"world\"", reader[0]);
            Assert.AreEqual("two", reader[1]);
        }

        [Test]
        public void TestTwoRows()
        {
            StringReader stringReader = new StringReader("one\r\ntwo\r\n");
            CSVStreamReader reader = new CSVStreamReader(stringReader, ";");
            Assert.IsFalse(reader.EndOfFile);
            Assert.AreEqual(1, reader.Columns);

            reader.MoveNext();

            Assert.IsFalse(reader.EndOfFile);
            Assert.AreEqual(1, reader.Columns);

            reader.MoveNext();

            Assert.IsTrue(reader.EndOfFile, "Expected end of file");
        }

        [Test]
        public void TestRowCounter()
        {
            StringReader stringReader = new StringReader("one\r\ntwo\r\n");
            CSVStreamReader reader = new CSVStreamReader(stringReader, ";");
            Assert.IsFalse(reader.EndOfFile);

            Assert.AreEqual(1, reader.Row, "1st row should be row #1");

            reader.MoveNext();

            Assert.IsFalse(reader.EndOfFile);
            Assert.AreEqual(2, reader.Row);

            reader.MoveNext();

            Assert.IsTrue(reader.EndOfFile, "Expected end of file");
        }

        [Test]
        public void TestRowCounterEmptyFile()
        {
            StringReader stringReader = new StringReader(String.Empty);
            CSVStreamReader reader = new CSVStreamReader(stringReader, ";");
            Assert.IsTrue(reader.EndOfFile);

            Assert.AreEqual(0, reader.Row, "1st row should be row #1");
        }

        [Test]
        public void TestLoadFromFile(
            [Values("SampleCSV_1.csv", "EmptyFile.csv", "Inductive_Sensors.csv", "Motion_Controller.csv")] string filename)
        {
            string path = System.IO.Path.Combine(@"..\..\SampleFiles", filename);

            using (StreamReader reader = new StreamReader(path, Encoding.UTF8))
            {
                CSVStreamReader csv = new CSVStreamReader(reader, ";");

                while (!csv.EndOfFile)
                {
                    Assert.IsTrue(csv.Columns > 0);
                    for (int i = 0; i < csv.Columns;i++ )
                    {
                        var value = csv[i];
                    }

                    csv.MoveNext();
                }
            }
        }
    }
}
